# 一、基础条件查询
# 1 基本查询
# get查询单一结果. 如果不存在会抛出模型类.DoesNotExist异常。
from book.models import BookInfo, PeopleInfo
# 查询 id=1 的 图书
BookInfo.objects.get(id=1)
# 如果 id=5 不存在，抛异常 DoesNotExist
BookInfo.objects.get(id=5)

# all查询多个结果。
BookInfo.objects.all()

# count查询结果数量。
#查询 图书 总的数量
BookInfo.objects.count()
#查询 人物总的数量
PeopleInfo.objects.count()


# 2 过滤查询
"""
# 实现SQL中的where功能，包括:
        - filter过滤出多个结果
        - exclude排除掉符合条件剩下的结果
        - get过滤单一结果
对于过滤条件的使用，上述三个方法相同，故仅以filter进行讲解。

过滤条件的表达语法如下:
    属性名称__比较运算符=值
     属性名称和比较运算符间使用两个下划线，所以属性名不能包括多个下划线
"""
# 1） 相等 -- exact：表示判等。
# 例：查询编号为1的图书。
BookInfo.objects.get(is__exact=1)
# 简写
BookInfo.objects.get(id=1)
# pk: primary(主要的) key（键）
BookInfo.objects.get(pk=1)

#2）模糊查询 -- contains：是否包含。
# 例：查询书名包含'传'的图书。
BookInfo.objects.filter(name__contains='传')

# startswith、endswith:以指定值开头或结尾.
#例：查询书名以'部’结尾的图书
BookInfo.objects.filter(name__endswith='部')
#例：查询书名以'射’开头的图书
BookInfo.objects.filter(name__startswith='射')
#以上运算符都区分大小写，在这些运算符前加上i表示不区分大小写，如iexact、icontains、istartswitlh,iendswith.


#3）空查询--isnull：是否为null。
#例：查询书名为空的图书。
BookInfo.objects.filter(name__isnull=True)
#例：查询书名不为空的图书
BookInfo.objects.filter(name__isnull=False)


# 4）范围查询--in：是否包含在范围内。
#例：查询编号id 为1或3或5的图书
BookInfo.objects.filter(id__in=[1,3,5])


#5）比较查询
"""

    gt大于(greater then)
    gte大于等于(greater then equal)
    lt小于（less then)
    lte小于等于(less then equal)
"""
#例：查询编号id 大于3的图书
BookInfo.obiects,filter(id__at=3)
BookInfo.objects.filter(id__lte=2)


#不等于的运算符，使用exclude()过滤器。
#例：查询编号不等于3的图书
BookInfo.objects.exclude(id=3)

# 6）日期查询 # year、month、day、week_day、hour、minute、second：对日期时间类型的属性进行运算
#例：查询pub_date 是1980年发表的图书。
BookInfo.objects.filter(pub_date__year=1980)

#例：查询pub_date 1990年1月1日后发表的图书。

BookInfo.objects.filter(pub_date__gt='1990-1-1')



#二、F和对象
"""
1.F对象 
   之前的查询都是对象的属性与常量值比较，两个属性怎么比较呢？答：使用F对象，被定义在django.db.models中
语法如下: 
    F(属性名) 
例：查询阅读量大于等于评论量的图书。
"""
# 导包
from django.db.models import F, Q
#查询阅读量readcount 大于等于评论量commentcount 的图书。
BookInfo.objects.filter(readcount__gte=F('commentcount'))

#可以在F对象上使用算数运算。
#查询阅读量readcount 大于等于 2倍评论量commentcount 的图书。
BookInfo.objects.filter(readcount__gte=F('commentcount')*2)
"""
2.Q对象
   多个过滤器逐个调用表示逻辑与关系，同sql语句中where部分的and关键字。
    
"""
#例：查询阅读量readcount 大于20，并且编号id 小于3的图书。
BookInfo.objects.filter(readcount__gt=20, id__lt=3)

#查询阅读量readcount 大于20，或编号id小于3的图书，只能使用Q对象实现
BookInfo.objects.filter(Q(readcount__gt=20)| Q(id__lt=3))
#查询编号id 不等于3的图书。
#Q对象前可以使用~操作符，表示非not.
BookInfo.objects.filter(~Q(id=3))
#查询编号id 不等于1和3的图书。
BookInfo.objects.filter(~Q(id__in=[1,3]))



#三、聚合函数和排序函数
#1.使用aggregate(）过滤器调用聚合函数，聚合函数：Avg平均，Count 数量，Max最大，Min最小，Sum求和，被定义在django.db.models中.
from django.db.models import Sum,Max, Avg, Count, Min
#例：查询图书的总阅读量readcount.
BookInfo.objects.aggregate(Sum('readcount'))
#查询图书的最大评论量commentcount.
BookInfo.objects.aggregate(Max('commentcount'))
#查询图书平均阅dcount
BookInfo.objects.aggregate(Avg('readcount'))

#2.排序
#使用order_by对结果进行排序
#默认按照主键升序排列
BookInfo.objects.all()
#按照给定的字段名阅读量readcount（列名）进行升序排序
BookInfo.objects.all().order_by('readcount')


#按照给定的字段名评论量commentcount（列名)进行降序排序
BookInfo.objects.all().order_by('-commentcount')
#按照给定的字段名出版日期pub_date（列名）进行升序/降序排序
BookInfo.objects.all().order_by('pub_date')
BookInfo.objects.all().order_by('-pub_date')


# 四、级联查询
# 1.关联查询
# 1.1 由一到多的访问语法：一对应的模型类对象.多对应的模型类名小写_set
# 例：查询 书籍 id为1的 所有人物信息
# 一对应的模型类对象
book = BookInfo.objects.get(id=1)
# 对象.多对应的模型类名小写_set，通过all()返回所有人物
book.peopleinfo_set.all()

# 例：查询 书籍名称 name为'雪山飞狐‘的 所有人物信息
book = BookInfo.objects.get(name='雪山飞狐')
book.peopleinfo_set.all()

# 1.2 由多到一的访问语法:多对应的模型类对象,多对应的模型类中的关系类属性名
# 例：查询 人物 id为1的 书籍信息
# 多对应的模型类对象
people = PeopleInfo.objects.get(id=1)
# 对象.多对应的模型类中的关系类属性名
people.book

# 1.3 访问一对应的模型类关联对象的id语法：多对应的模型类对象.关联类属性_id
# 例：查询 id=1 的人物 所属 图书的id
people.book_id

# 例：查询 人物名字 name为‘虚竹‘的 书籍信息
people = PeopleInfo.objects.get(name='虚竹')
people.book


#2.关联过滤查询
#2.1 由多模型类条件查询一模型类数据：
"""
语法如下：

     关联模型类名小写__属性名__条件运算符=值
注意：如果没有”运算符“部分，表示等于。
"""
#查询图书，要求图书人物name 为”郭靖”
book = BookInfo.objects.get(peopleinfo__name='郭靖')

#查询图书，要求图书中人物的描述description 包含”八”
books = BookInfo.objects.filter(peopleinfo__description__contains='八')

#2.2由一模型类条件查询多模型类数据：
"""
语法如下：
     一模型类关联属性名__一模型类属性名__条件运算符=值
注意：如果没有”__运算符”部分，表示等于。
"""
#查询书名name为“天龙八部”的所有人物
peoples = PeopleInfo.objects.filter(book_name='天龙八部')

#查询图书阅读量readcount大于30的所有人物
peoples = PeopleInfo.objects.filter(book__readcount__gt=30)